package cn.iocoder.yudao.module.iot.service.device.energy;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
import cn.iocoder.yudao.module.iot.dal.redis.device.DeviceEnergyRedisDAO;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;

/**
 * IoT 设备【能源数据】Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Slf4j
public class IotDeviceEnergyServiceImpl implements IotDeviceEnergyService {

    @Resource
    private DeviceEnergyRedisDAO deviceEnergyRedisDAO;

    @Override
    public void processDeviceEnergyData(IotDeviceDO device, IotDeviceMessage message) {
        if (message.getParams() == null || !(message.getParams() instanceof Map)) {
            log.debug("[processDeviceEnergyData][设备({}) 消息参数为空或格式不正确]", device.getId());
            return;
        }

        Map<String, Object> params = (Map<String, Object>) message.getParams();
        String energyDataStr = (String) params.get("energy");
        
        if (StrUtil.isEmpty(energyDataStr)) {
            log.debug("[processDeviceEnergyData][设备({}) 消息中没有energy字段]", device.getId());
            return;
        }

        try {
            // 安全解析energy数据
            Map<String, Object> energyData = null;
            if (energyDataStr.startsWith("{") && energyDataStr.endsWith("}")) {
                @SuppressWarnings("unchecked")
                Map<String, Object> parsed = JSONUtil.toBean(energyDataStr, Map.class);
                energyData = parsed;
            }
            
            if (energyData == null) {
                log.warn("[processDeviceEnergyData][设备({}) JSON解析失败, energyData: {}]", device.getId(), energyDataStr);
                return;
            }
            
            // 提取能源数据字段
            Double voltage = getDoubleValue(energyData, "voltage");
            String current = getStringValue(energyData, "current");
            Double power = getDoubleValue(energyData, "power");
            Double timestamp = getDoubleValue(energyData, "timestamp");
            
            // 构建能源数据记录
            Map<String, Object> energyRecord = new HashMap<>();
            energyRecord.put("deviceId", device.getId());
            energyRecord.put("voltage", voltage != null ? voltage : 0.0);
            energyRecord.put("current", current != null ? current : "0.000");
            energyRecord.put("power", power != null ? power : 0.0);
            energyRecord.put("timestamp", timestamp != null ? timestamp : System.currentTimeMillis());
            energyRecord.put("reportTime", message.getReportTime());
            energyRecord.put("dataIndex", getNextDataIndex(device.getId()));
            
            // 保存到Redis
            deviceEnergyRedisDAO.saveEnergyData(device.getId(), energyRecord);
            
            log.info("[processDeviceEnergyData][设备({}) 能源数据处理成功, voltage: {}, current: {}, power: {}]", 
                    device.getId(), voltage, current, power);
                    
        } catch (Exception e) {
            log.error("[processDeviceEnergyData][设备({}) 能源数据处理失败, energyData: {}]", 
                    device.getId(), energyDataStr, e);
        }
    }

    @Override
    public List<Map<String, Object>> getDeviceEnergyHistory(Long deviceId, int limit) {
        return deviceEnergyRedisDAO.getEnergyHistory(deviceId, limit);
    }

    @Override
    public Map<String, Object> getLatestDeviceEnergy(Long deviceId) {
        return deviceEnergyRedisDAO.getLatestEnergy(deviceId);
    }

    /**
     * 获取下一个数据索引
     */
    private int getNextDataIndex(Long deviceId) {
        List<Map<String, Object>> history = deviceEnergyRedisDAO.getEnergyHistory(deviceId, 1);
        if (history.isEmpty()) {
            return 1;
        }
        Map<String, Object> latest = history.get(0);
        Integer currentIndex = (Integer) latest.get("dataIndex");
        return currentIndex != null ? currentIndex + 1 : 1;
    }

    /**
     * 安全获取Double值
     */
    private Double getDoubleValue(Map<String, Object> map, String key) {
        Object value = map.get(key);
        if (value == null) {
            return null;
        }
        if (value instanceof Number) {
            return ((Number) value).doubleValue();
        }
        if (value instanceof String) {
            try {
                return Double.parseDouble((String) value);
            } catch (NumberFormatException e) {
                return null;
            }
        }
        return null;
    }

    /**
     * 安全获取String值
     */
    private String getStringValue(Map<String, Object> map, String key) {
        Object value = map.get(key);
        return value != null ? value.toString() : null;
    }
} 